package com.thesis.manage.service.impl;

import com.github.crab2died.ExcelUtils;
import com.github.pagehelper.PageInfo;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.thesis.manage.common.exception.CommonException;
import com.thesis.manage.common.threadpool.TraceThreadPoolExecutor;
import com.thesis.manage.domain.Student;
import com.thesis.manage.domain.StudentTeacher;
import com.thesis.manage.domain.Teacher;
import com.thesis.manage.domain.TeacherRole;
import com.thesis.manage.service.*;
import com.thesis.manage.service.constant.ErrorMessage;
import com.thesis.manage.service.model.RoleEnum;
import com.thesis.manage.service.module.excel.GroupExcel;
import com.thesis.manage.service.module.vo.StudentVO;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;

/**
 * @author php
 * @date 2018/2/24
 */
@Service
public class AnswerServiceImpl implements AnswerService {
    @Resource
    private TeacherService teacherService;

    @Resource
    private TeacherRoleService teacherRoleService;

    @Resource
    private StudentService studentService;

    @Resource
    private StudentTeacherService studentTeacherService;

    @Override
    public PageInfo<Teacher> list(String collegeName, Pageable pageable) {
        Assert.notNull(collegeName, ErrorMessage.PARAMS_IS_NULL);
        TeacherRole teacherRole = new TeacherRole();
        teacherRole.setCollegeName(collegeName);
        teacherRole.setRoleId(RoleEnum.GUIDETEACHER.getValue().longValue());
        //获取指导教师
        PageInfo<TeacherRole> list = this.teacherRoleService.list(teacherRole, pageable);
        List<Teacher> teachers = new ArrayList<>();
        PageInfo<Teacher> objectPageInfo = new PageInfo<>();
        try {
            if (list != null && CollectionUtils.isNotEmpty(list.getList())) {
                Teacher obj;
                for (TeacherRole t : list.getList()) {
                    Teacher teacher = this.teacherService.findById(t.getTeacherId());
                    obj = new Teacher();
                    obj.setId(teacher.getId());
                    obj.setName(teacher.getName());
                    obj.setImage(teacher.getImage());
                    obj.setTeacherNumber(teacher.getTeacherNumber());
                    teachers.add(obj);
                }
                objectPageInfo.setTotal(list.getTotal());
                objectPageInfo.setList(teachers);
                objectPageInfo.setPageNum(list.getPageNum());
                objectPageInfo.setPageSize(list.getPageSize());
                objectPageInfo.setPages(list.getPages());
            }
        } catch (Exception e) {
            throw new CommonException("data covert failed", "教师信息转换失败");
        }
        return objectPageInfo;
    }

    @Override
    public void importGroupInfo(MultipartFile file) {
        try {
            List<GroupExcel> groupExcels = ExcelUtils.getInstance().readExcel2Objects(file.getInputStream(), GroupExcel.class);
            if (CollectionUtils.isNotEmpty(groupExcels)) {
                Map<String, List<GroupExcel>> group = this.group(groupExcels);
                Collection<List<GroupExcel>> values = group.values();
                ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                        .setNameFormat("student-teacher-group-pool-%d").build();
                ExecutorService pool = new TraceThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(),
                        0L, TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
                for (List<GroupExcel> list : values) {
                    pool.execute(() -> {
                        StudentTeacher studentTeacher;
                        for (GroupExcel groupExcel : list) {
                            studentTeacher = new StudentTeacher();
                            studentTeacher.setStudentNumber(groupExcel.getStudentNumber());
                            studentTeacher.setTeacherNumber(groupExcel.getTeacherNumber());
                            this.studentTeacherService.save(studentTeacher);
                        }
                    });
                }
                pool.shutdown();//gracefully shutdown
            }
        } catch (Exception e) {
            throw new CommonException("import group info failed", "导入分组信息失败");
        }

    }

    @Override
    public List<StudentVO> findGroupInfoByTeacherNumber(String teacherNumber) {
        Assert.notNull(teacherNumber, ErrorMessage.PARAMS_IS_NULL);
        StudentTeacher studentTeacher = new StudentTeacher();
        studentTeacher.setTeacherNumber(teacherNumber);
        List<StudentTeacher> list = this.studentTeacherService.findAll(studentTeacher);
        List<StudentVO> result = null;
        if (CollectionUtils.isNotEmpty(list)) {
            result = new ArrayList<>();
            StudentVO stu;
            try {
                for (StudentTeacher st : list) {
                    Student student = this.studentService.findByStudentNumber(st.getStudentNumber());
                    if (student == null) {
                        this.studentTeacherService.delete(st.getId());
                    }
                    stu = new StudentVO();
                    PropertyUtils.copyProperties(stu, student);
                    stu.setId(st.getId());
                    result.add(stu);
                }
            } catch (Exception e) {
                throw new CommonException("data.convert.failed", ErrorMessage.OBJECT_CONVERT_FAILED);
            }
        }
        return result;
    }

    @Override
    public void add(String studentNumber, String teacherNumber) {
        boolean isEmpty = StringUtils.isBlank(studentNumber) || StringUtils.isBlank(teacherNumber);
        Assert.state(!isEmpty, ErrorMessage.PARAMS_IS_NULL);
        Student student = this.studentService.findByStudentNumber(studentNumber);
        if (student == null) {
            throw new CommonException("The student not exist", "该学生不存在");
        }
        StudentTeacher studentTeacher = new StudentTeacher();
        studentTeacher.setStudentNumber(studentNumber);
        StudentTeacher one = this.studentTeacherService.findByOne(studentTeacher);
        if (one != null) {
            throw new CommonException("The student has been selected", "该学生已被选择");
        }
        studentTeacher.setTeacherNumber(teacherNumber);
        System.out.println(studentTeacher);
        this.studentTeacherService.save(studentTeacher);

    }

    /**
     * 导入信息安装指导教师分组
     *
     * @param list 导入信息
     * @return 分组后的信息
     */
    private Map<String, List<GroupExcel>> group(List<GroupExcel> list) {
        Map<String, List<GroupExcel>> skuIdMap = new HashMap<>(20);
        for (GroupExcel groupExcel : list) {
            List<GroupExcel> tempList = skuIdMap.get(groupExcel.getTeacherNumber());
            //如果取不到数据,那么直接new一个空的ArrayLis
            if (tempList == null) {
                tempList = new ArrayList<>();
                tempList.add(groupExcel);
                skuIdMap.put(groupExcel.getTeacherNumber(), tempList);
            } else {
                //某个sku之前已经存放过了,则直接追加数据到原来的List里
                tempList.add(groupExcel);
            }
        }
        return skuIdMap;
    }
}
